package com.pangolin.pangolinim.service.thread;


import android.util.Base64;

import com.orhanobut.logger.Logger;
import com.pangolin.pangolinim.app.BroadcastMsg;
import com.pangolin.pangolinim.app.mainApp;
import com.pangolin.pangolinim.net.NetFormat;
import com.pangolin.pangolinim.net.Netpackage;
import com.pangolin.pangolinim.service.system.AppRuntime;
import com.pangolin.pangolinim.service.thread.base.baseThread;
import com.pangolin.pangolinim.sqlite.DBContact;
import com.pangolin.pangolinim.sqlite.DBMessage;
import com.pangolin.pangolinim.sqlite.DBSession;
import com.pangolin.pangolinim.sqlite.DBUser;
import com.pangolin.pangolinim.utils.AESUtil;
import com.pangolin.pangolinim.utils.BundleUtil;
import com.pangolin.pangolinim.utils.DBHelperUtil;
import com.pangolin.pangolinim.utils.DHUtil;
import com.pangolin.pangolinim.utils.DateUtil;
import com.pangolin.pangolinim.utils.GsonUtil;
import com.pangolin.pangolinim.utils.NotifyUtil;

import org.json.JSONException;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class recvThread extends baseThread {
    @Override
    public void run() {
        if(mSocket == null || !mSocket.isconnect()){
            Logger.e("recvThread:run:socket error");
            //TODO:将错误信息返回给上层UI
            BundleUtil bundleUtil = new BundleUtil(BroadcastMsg.SIG_CORE_NETERR ,"network error");
            BroadcastSender(bundleUtil.getBundle());
            return;
        }
        Logger.d("recvThread:run:recvThread started");
        try {
            //TODO:循环监听服务器消息
            while (true) {
                //接收包头部分
                byte headByte[] = mSocket.recv(16);
                Netpackage pkg = new Netpackage();
                pkg.formatHead(headByte);
                //接收剩下的包数据
                byte bodyByte[] = mSocket.recv(pkg.getPackageLen() - 16);
                byte[] packageByte = new byte[pkg.getPackageLen()];
                //合并数据
                System.arraycopy(headByte, 0, packageByte, 0, headByte.length);
                System.arraycopy(bodyByte, 0, packageByte, headByte.length, bodyByte.length);
                //格式化整个包
                pkg.formatAll(packageByte);

                /** 分发处理各种消息类型 */
                switch (pkg.getCommand()){
                    case Netpackage.COM_RE_REGISTER:        //注册请求返回
                        NetRegister(pkg.getBody());
                        break;
                    case Netpackage.COM_RE_LOGIN:           //登陆请求返回
                        NetLogin(pkg.getBody());
                        break;
                    case Netpackage.COM_RE_LOGOUT:          //退出登陆请求返回
                        NetLogout(pkg.getBody());
                        break;
                    case Netpackage.COM_RE_FINDFRIEND:      //搜索好友请求返回
                        NetFindFriend(pkg.getBody());
                        break;
                    case Netpackage.COM_RE_REPASS:          //修改密码请求返回
                        NetRepass(pkg.getBody());
                        break;
                    case Netpackage.COM_RE_USERINFO:        //修改用户信息请求返回
                        NetReinfo(pkg.getBody());
                        break;
                    case Netpackage.COM_RE_MESSAGE:         //发送消息请求返回
                        NetMessage(pkg.getBody());
                        break;
                    case Netpackage.COM_RE_OPERATEFRIEND:   //添加好友请求返回
                        NetOperateFriend(pkg.getBody());
                        break;
                    case Netpackage.COM_RE_CONFIRMFRIEND:   //确认好友申请请求返回
                        NetConfirmFriend(pkg.getBody());
                        break;
                    case Netpackage.COM_RE_DELFRIEND:       //删除好友请求返回
                        NetDeleteFriend(pkg.getBody());
                        break;
                    case Netpackage.COM_RE_FRIENDLIST:      //获取联系人列表请求返回
                        NetFriendList(pkg.getBody());
                        break;
                    case Netpackage.COM_RE_OFF_MESSAGE:     //获取离线消息请求返回
                        NetOffMessage(pkg.getBody());
                        break;
                    case Netpackage.CLI_OPERATEFRIEND:      //客户端消息 添加好友申请
                        ClientOperateFriend(pkg.getBody());
                        break;
                    case Netpackage.CLI_CONFIRMFRIEND:      //客户端消息 确认好友申请
                        ClientConfirmFriend(pkg.getBody());
                        break;
                    case Netpackage.CLI_DELFRIEND:          //客户端消息 删除好友
                        ClientDeleteFriend(pkg.getBody());
                        break;
                    case Netpackage.CLI_MESSAGE:            //客户端消息 普通消息
                        ClientMessage(pkg.getBody());
                        break;
                }
            }
        } catch (JSONException e){
            //TODO:将错误信息返回给上层UI
            Logger.e("recvThread:FormatMessage:error:%s", e.getMessage());
            BundleUtil bundleUtil = new BundleUtil(BroadcastMsg.SIG_CORE_SYSERR , e.getMessage());
            BroadcastSender(bundleUtil.getBundle());
        }catch (Exception e) {
            //TODO:将错误信息返回给上层UI
            Logger.e("recvThread:run:error:%s", e.getMessage());
            BundleUtil bundleUtil = new BundleUtil(BroadcastMsg.SIG_CORE_SYSERR ,  e.getMessage());
            BroadcastSender(bundleUtil.getBundle());
        }
        Logger.d("recvThread:run:recvThread stoped");
    }

    /** *********************************   以下是各类消息的功能函数   *********************************/

    //注册请求返回
    private void NetRegister(String data) throws JSONException{
        Map<String , Object> resMap = NetFormat.registerDecode(data);
        Map<String, Object> brocastMap = new HashMap<String, Object>();
        brocastMap.put("type" , BroadcastMsg.DATA_CORE_REG);
        brocastMap.put("result" , (int)resMap.get("result"));
        brocastMap.put("uid" , (int)resMap.get("uid"));
        brocastMap.put("msg" , (String)resMap.get("msg"));
        BundleUtil bundleUtil = new BundleUtil(BroadcastMsg.SIG_CORE_DATA , brocastMap , null);
        BroadcastSender(bundleUtil.getBundle());
    }

    //登陆请求返回
    private void NetLogin(String data) throws Exception{
        Map<String , Object> resMap = NetFormat.loginDecode(data);
        //Logger.d(resMap);
        if( (int)resMap.get("result") == 0){
            mUid = (int) resMap.get("uid");
            mKey = (String) resMap.get("key");
            mHeadimg = (String) resMap.get("headimg");
            mUsername = (String) resMap.get("name");
            //打开本地数据库
            DBHelperUtil.getInstance().OpenDB(mainApp.getContext() , String.valueOf(mUid) , 1);
            //自动同步联系人列表
            Netpackage pkgSend = NetFormat.friendListEndcode(mUid , mKey);
            byte msgData[] = pkgSend.getByte();
            mSocket.send(msgData , msgData.length);
        }
        Map<String, Object> brocastMap = new HashMap<String, Object>();
        brocastMap.put("type" , BroadcastMsg.DATA_CORE_LOGIN);
        brocastMap.put("result" , (int)resMap.get("result"));
        brocastMap.put("msg" , (String)resMap.get("msg"));
        brocastMap.put("uid" , mUid);
        brocastMap.put("name" , mUsername);
        brocastMap.put("headimg" , mHeadimg);
        BundleUtil bundleUtil = new BundleUtil(BroadcastMsg.SIG_CORE_DATA , brocastMap , null);
        BroadcastSender(bundleUtil.getBundle());
    }

    //退出登陆请求返回
    private void NetLogout(String data) throws JSONException{
        Map<String , Object> resMap = NetFormat.logoutDecode(data);
        Map<String , Object> brocastMap = new HashMap<>();
        brocastMap.put("type" , BroadcastMsg.DATA_CORE_LOGOUT);
        brocastMap.put("msg" , (String)resMap.get("msg"));
        brocastMap.put("result" , (int)resMap.get("result"));
        if((int)resMap.get("result") == 0){
            //关闭本地数据库
            DBHelperUtil.getInstance().close();
        }
        BundleUtil bundleUtil = new BundleUtil(BroadcastMsg.SIG_CORE_DATA , brocastMap , null);
        BroadcastSender(bundleUtil.getBundle());
    }

    //搜索好友请求返回
    private void NetFindFriend(String data) throws JSONException{
        Map<String , Object> resMap = NetFormat.findFriendDecode(data);
        Map<String , Object> brocastMap = new HashMap<>();
        brocastMap.put("type" , BroadcastMsg.DATA_CORE_FINDUSER);
        brocastMap.put("result" , (int)resMap.get("result"));
        brocastMap.put("name" , (String)resMap.get("friend_name"));
        brocastMap.put("uid" , (int)resMap.get("friend_uid"));
        brocastMap.put("headimg" , (String)resMap.get("friend_headimg"));
        brocastMap.put("msg" , (String)resMap.get("msg"));
        BundleUtil bundleUtil = new BundleUtil(BroadcastMsg.SIG_CORE_DATA , brocastMap , null);
        BroadcastSender(bundleUtil.getBundle());
    }

    //修改密码请求返回
    private void NetRepass(String data) throws JSONException{
        Map<String , Object> resMap = NetFormat.repassDecode(data);
        Map<String , Object> brocastMap = new HashMap<>();
        brocastMap.put("type" , BroadcastMsg.DATA_CORE_REPASS);
        brocastMap.put("result" , (int)resMap.get("result"));
        brocastMap.put("msg" , (String)resMap.get("msg"));
        BundleUtil bundleUtil = new BundleUtil(BroadcastMsg.SIG_CORE_DATA , brocastMap , null);
        BroadcastSender(bundleUtil.getBundle());
    }

    //修改用户信息返回
    private void NetReinfo(String data) throws JSONException{
        Map<String , Object> resMap = NetFormat.setUserinfoDecode(data);
        Map<String , Object> brocastMap = new HashMap<>();
        brocastMap.put("type" , BroadcastMsg.DATA_CORE_REINFO);
        brocastMap.put("result" , (int)resMap.get("result"));
        brocastMap.put("msg" , (String)resMap.get("msg"));
        if((int)resMap.get("result") == 0){
            mUsername = usernameTmp;
            mHeadimg = headimgTmp;
        }
        BundleUtil bundleUtil = new BundleUtil(BroadcastMsg.SIG_CORE_DATA , brocastMap , null);
        BroadcastSender(bundleUtil.getBundle());
    }

    //普通消息请求返回
    private void NetMessage(String data) throws JSONException{
        Map<String , Object> resMap = NetFormat.messageDecode(data);
        Map<String , Object> brocastMap = new HashMap<>();
        brocastMap.put("type" , BroadcastMsg.DATA_CORE_SENDMSG);
        brocastMap.put("result" , (int)resMap.get("result"));
        brocastMap.put("mid" , (String)resMap.get("mid"));
        brocastMap.put("msg" , (String)resMap.get("msg"));
        if((int)resMap.get("result") == 0){
            //修改数据库设置char_msg.status字段为已送达
            DBMessage msg = new DBMessage();
            msg.setMid((String)resMap.get("mid"));
            msg.setStatus(2);
            DBHelperUtil.getInstance().update_msg(msg);
        }
        BundleUtil bundleUtil = new BundleUtil(BroadcastMsg.SIG_CORE_DATA , brocastMap , null);
        BroadcastSender(bundleUtil.getBundle());
    }

    //添加好友请求返回
    private void NetOperateFriend(String data) throws JSONException {
        Map<String , Object> resMap = NetFormat.operateFriendDecode(data);
        Map<String , Object>brocastMap = new HashMap<>();
        brocastMap.put("type" , BroadcastMsg.DATA_CORE_OPERATE);
        brocastMap.put("result" , (int)resMap.get("result"));
        brocastMap.put("msg" , (String)resMap.get("msg"));
        BundleUtil bundleUtil = new BundleUtil(BroadcastMsg.SIG_CORE_DATA , brocastMap , null);
        BroadcastSender(bundleUtil.getBundle());
    }

    //确认好友申请请求返回
    private void NetConfirmFriend(String data)throws JSONException{
        Map<String, Object> resMap = NetFormat.confirmFriendDecode(data);
        Map<String, Object> brocastMap = new HashMap<>();
        brocastMap.put("type", BroadcastMsg.DATA_CORE_CONFIRM);
        brocastMap.put("result", (int) resMap.get("result"));
        brocastMap.put("msg", (String) resMap.get("msg"));
        BundleUtil bundleUtil = new BundleUtil(BroadcastMsg.SIG_CORE_DATA, brocastMap, null);
        BroadcastSender(bundleUtil.getBundle());
    }

    //删除好友申请返回
    private void NetDeleteFriend(String data) throws JSONException{
        Map<String, Object> resMap = NetFormat.delFriendDecode(data);
        Map<String, Object> brocastMap = new HashMap<>();
        brocastMap.put("type", BroadcastMsg.DATA_CORE_DELETE);
        brocastMap.put("result", (int) resMap.get("result"));
        brocastMap.put("msg", (String) resMap.get("msg"));
        BundleUtil bundleUtil = new BundleUtil(BroadcastMsg.SIG_CORE_DATA, brocastMap, null);
        BroadcastSender(bundleUtil.getBundle());
    }

    //获取联系人列表请求返回
    private void NetFriendList(String data) throws JSONException{
        Map<String, Object> resMap = NetFormat.friendListDecode(data);
        if ((int) resMap.get("result") == 0) {
            //将联系人存入contacts表
            int num = (int) resMap.get("num");
            if(num > 0) {
                List<Map<String, Object>> contactList = (List<Map<String, Object>>) resMap.get("contacts");
                Iterator<Map<String, Object>> iterator = contactList.iterator();
                while (iterator.hasNext()) {
                    Map<String, Object> contactMap = iterator.next();
                    DBUser user = DBHelperUtil.getInstance().get_oneuser((int)contactMap.get("uid"));
                    String seckey = (user == null ? null : user.getSeckey());
                    DBContact contact = new DBContact();
                    contact.setUid((int)contactMap.get("uid"));
                    contact.setName((String)contactMap.get("name"));
                    contact.setHeadimg((String)contactMap.get("headimg"));
                    contact.setSeckey(seckey);
                    contacts.insert_contact(contact);
                }
            }
            //判断是否接收完毕
            int contactsCount = contacts.count_contacts();  //获取contacts表条目数
            if(num <= contactsCount){   //达到num字段数量就发送广播通知上层
                //序列化ContactList
                String str_contacts = GsonUtil.toJson(contacts);
                //发送给UI
                Map<String, Object> brocastMap = new HashMap<>();
                brocastMap.put("type", BroadcastMsg.DATA_CORE_CONTACTS);
                brocastMap.put("result", (int) resMap.get("result"));
                brocastMap.put("msg", (String) resMap.get("msg"));
                brocastMap.put("contacts" , str_contacts);
                BundleUtil bundleUtil = new BundleUtil(BroadcastMsg.SIG_CORE_DATA, brocastMap, null);
                BroadcastSender(bundleUtil.getBundle());
            }
        }
    }

    //获取离线消息请求返回
    private void NetOffMessage(String data) throws JSONException{
        Map<String, Object> resMap = NetFormat.offMessageDecode(data);
        Map<String , Object>brocastMap = new HashMap<>();
        brocastMap.put("type" , BroadcastMsg.DATA_CORE_OFFMSG);
        brocastMap.put("result" , (int)resMap.get("result"));
        brocastMap.put("msg" , (String)resMap.get("msg"));
        BundleUtil bundleUtil = new BundleUtil(BroadcastMsg.SIG_CORE_DATA , brocastMap , null);
        BroadcastSender(bundleUtil.getBundle());
    }

    //客户端间消息 好友申请
    private void ClientOperateFriend(String data) throws JSONException{
        Map<String, Object> resMap = NetFormat.getMapForJson(data);
        if((int)resMap.get("to") == mUid){
            String pubkeyb = (String)resMap.get("pubkey");
            DBUser user = new DBUser();
            user.setUid((int)resMap.get("from"));
            user.setName((String)resMap.get("name"));
            user.setHeadimg((String)resMap.get("headimg"));
            user.setPubkeyb(pubkeyb);
            user.setType(3);
            DBHelperUtil.getInstance().insert_user(user);
            //通知上层UI
            Map<String , Object>brocastMap = new HashMap<>();
            brocastMap.put("type" , BroadcastMsg.DATA_CORE_CLIOPERATE);
            brocastMap.put("name" , (String)resMap.get("name"));
            BundleUtil bundleUtil = new BundleUtil(BroadcastMsg.SIG_CORE_DATA , brocastMap , null);
            BroadcastSender(bundleUtil.getBundle());
            //发送系统通知
            NotifyUtil.setNotificationChannel(mainApp.getContext());
            NotifyUtil.show(mainApp.getContext(), "PangolinIM", "您有来自"+String.valueOf((int) resMap.get("from"))+"的好友申请请及时处理", null);
        }
    }

    //客户端消息 确认好友申请
    private void ClientConfirmFriend(String data) throws JSONException{
        Map<String, Object> resMap = NetFormat.getMapForJson(data);
        if((int)resMap.get("to") == mUid) {
            try{
                //计算对称密钥，并存储进数据库user表
                byte publicKeyB[]  = Base64.decode(((String)resMap.get("pubkey")).getBytes() , Base64.NO_WRAP);
                byte prilicKeyA[]  = Base64.decode(mainApp.getPrikey().getBytes() , Base64.NO_WRAP);
                byte localKeyA[] = DHUtil.getSecretKey(publicKeyB, prilicKeyA);
                String seckey = Base64.encodeToString(localKeyA , Base64.NO_WRAP);
                //同步user表
                DBUser user = DBHelperUtil.getInstance().get_oneuser((int) resMap.get("from"));
                if(user == null){
                    BundleUtil bundleUtil = new BundleUtil(BroadcastMsg.SIG_CORE_SYSERR , "好友申请反馈：未找到申请记录");
                    BroadcastSender(bundleUtil.getBundle());
                    return;
                }
                user.setPubkeyb((String)resMap.get("pubkey"));
                user.setSeckey(seckey);
                user.setType(5);
                DBHelperUtil.getInstance().update_user(user);
                DBContact contact = contacts.get_onecontact((int) resMap.get("from"));
                if(contact != null){
                    contact.setSeckey(user.getSeckey());
                    contacts.update_contact(contact);
                }else{
                    DBContact newcontact = new DBContact();
                    newcontact.setUid(user.getUid());
                    newcontact.setName(user.getName());
                    newcontact.setHeadimg(user.getHeadimg());
                    newcontact.setSeckey(user.getSeckey());
                    contacts.insert_contact(newcontact);
                }
                //通知上层UI
                Map<String , Object>brocastMap = new HashMap<>();
                brocastMap.put("type" , BroadcastMsg.DATA_CORE_CLICONFIRM);
                brocastMap.put("uid" , user.getUid());
                brocastMap.put("name" , user.getName());
                brocastMap.put("headimg" , user.getHeadimg());
                BundleUtil bundleUtil = new BundleUtil(BroadcastMsg.SIG_CORE_DATA , brocastMap , null);
                BroadcastSender(bundleUtil.getBundle());
            }catch (Exception e){
                //TODO:将错误信息返回给上层UI
                Logger.d("好友申请反馈："+e.getMessage());
                BundleUtil bundleUtil = new BundleUtil(BroadcastMsg.SIG_CORE_SYSERR , "好友申请反馈："+e.getMessage());
                BroadcastSender(bundleUtil.getBundle());
            }
        }
    }

    //客户端消息 删除好友
    private void ClientDeleteFriend(String data) throws JSONException{
        Map<String, Object> resMap = NetFormat.getMapForJson(data);
        if((int)resMap.get("to") == mUid) {
            //删除联系人列表
            contacts.delete_contact((int) resMap.get("from"));
            //删除最近会话列表
            sessions.delete_session((int) resMap.get("from"));
            //删除数据库chat_session表数据
            DBHelperUtil.getInstance().del_session((int) resMap.get("from"));
            Map<String , Object>brocastMap = new HashMap<>();
            brocastMap.put("type" , BroadcastMsg.DATA_CORE_CLIDELETE);
            brocastMap.put("uid" , (int) resMap.get("from"));
            BundleUtil bundleUtil = new BundleUtil(BroadcastMsg.SIG_CORE_DATA , brocastMap , null);
            BroadcastSender(bundleUtil.getBundle());
        }
    }

    //客户端消息 普通消息
    private void ClientMessage(String data) throws Exception{
        Map<String, Object> resMap = NetFormat.messageDecode(data);
        if((int)resMap.get("to") == mUid) {
            DBContact contact = contacts.get_onecontact((int)resMap.get("from"));
            String decryptMsg = (String)resMap.get("context");
            if(contact != null){
                decryptMsg = AESUtil.decrypt(decryptMsg , contact.getSeckey());
            }
            //将消息存入数据库chat_msg表
            DBMessage msg = new DBMessage();
            msg.setMid((String) resMap.get("mid"));
            msg.setIo(2);
            msg.setStatus(2);
            msg.setType((int)resMap.get("type"));
            msg.setUid((int)resMap.get("from"));
            msg.setMsgtext(decryptMsg);
            msg.setTimestamp((int)resMap.get("time"));
            DBHelperUtil.getInstance().insert_msg(msg);
            //更新会话消息
            DBSession session = new DBSession();
            DBContact dbContact = contacts.get_onecontact((int)resMap.get("from"));
            session.setUid(msg.getUid());
            if(dbContact != null){
                session.setName(dbContact.getName());
                session.setHeadimg(dbContact.getHeadimg());
            }
            session.setMsgtype(msg.getType());
            session.setLastmsg(decryptMsg);
            session.setLasttime(DateUtil.getWechatTime(msg.getTimestamp() * 1000l));
            DBSession oldsession = sessions.get_session((int)resMap.get("from"));
            if(oldsession != null){
                session.setUnread(oldsession.getUnread() + 1);
            }else{
                session.setUnread(1);
            }
            sessions.insert_session(session);
            //新建或修改数据库chat_session数据
            DBHelperUtil.getInstance().insert_session(session);
            //通知UI
            Map<String , Object>brocastMap = new HashMap<>();
            brocastMap.put("type" , BroadcastMsg.DATA_CORE_CLIMSG);
            brocastMap.put("uid" , msg.getUid());
            brocastMap.put("msgtype" , msg.getType());
            brocastMap.put("context" , msg.getMsgtext());
            brocastMap.put("mid" , msg.getMid());
            brocastMap.put("time" , msg.getTimestamp());
            BundleUtil bundleUtil = new BundleUtil(BroadcastMsg.SIG_CORE_DATA , brocastMap , null);
            BroadcastSender(bundleUtil.getBundle());
            //发送系统通知
            if(AppRuntime.getIsNotify() && AppRuntime.getSessionUid() != msg.getUid()){
                NotifyUtil.RingtonePlay();
            }
        }
    }

}
